home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 98 / Skunkware 98.iso / src / mail / pine3.96.tar.gz / pine3.96.tar / pine3.96 / pine / osdep / pipe.os2 < prev    next >
Text File  |  1996-05-23  |  8KB  |  248 lines

  1. #line 2 "osdep/pipe.os2"
  2. /*======================================================================
  3.     pipe
  4.     
  5.     Initiate I/O to and from a process.  These functions are similar to 
  6.     popen and pclose, but both an incoming stream and an output file are 
  7.     provided.
  8.    
  9.  ====*/
  10.  
  11. #include <process.h>
  12. #ifndef    STDIN_FILENO
  13. #define    STDIN_FILENO    0
  14. #endif
  15. #ifndef    STDOUT_FILENO
  16. #define    STDOUT_FILENO    1
  17. #endif
  18. #ifndef    STDERR_FILENO
  19. #define    STDERR_FILENO    2
  20. #endif
  21.  
  22. int     child_status;
  23.  
  24. void pipe_error_cleanup(PIPE_S **syspipe, char*cmd, char *op, char *res);
  25.  
  26.  
  27. /*----------------------------------------------------------------------
  28.      Spawn a child process and optionally connect read/write pipes to it
  29.  
  30.   Args: command -- string to hand the shell
  31.     outfile -- address of pointer containing file to receive output
  32.     errfile -- address of pointer containing file to receive error output
  33.     mode -- mode for type of shell, signal protection etc...
  34.   Returns: pointer to alloc'd PIPE_S on success, NULL otherwise
  35.  
  36.   This is a much simpler version than the UNIX pipe since it utilises
  37.   the EMX popen()/pclose() functions for OS/2 (and thereby avoides
  38.   fork() and its restrictions under OS/2). It is therefore not as
  39.   functional as the UNIX equivalents, and only understands a subset
  40.   of modes. All commands also invoke the system shell, but this is
  41.   of little consequence as there are no security problems and so forth
  42.   in the OS/2 environment.
  43.     PIPE_WRITE tells us we need to open a pipe to write the child's
  44.     stdin.
  45.     PIPE_READ tells us we need to open a pipe to read from the child's
  46.     stdout/stderr.  *NOTE*  Having neither of the above set means 
  47.     we're not setting up any pipes, just forking the child and exec'ing
  48.     the command.  Also, this takes precedence over any named outfile.
  49.     PIPE_STDERR means we're to tie the childs stderr to the same place
  50.     stdout is going.  *NOTE* This only makes sense then if PIPE_READ
  51.     or an outfile is provided.  Also, this takes precedence over any
  52.     named errfile.
  53.     PIPE_PROT means to protect the child from the usual nasty signals
  54.     that might cause premature death.  Otherwise, the default signals are
  55.     set so the child can deal with the nasty signals in its own way.     
  56.     PIPE_NOSHELL means we're to exec the command without the aid of
  57.     a system shell.  *NOTE* This negates the affect of PIPE_USER.
  58.     PIPE_USER means we're to try executing the command in the user's
  59.     shell.  Right now we only look in the environment, but that may get
  60.     more sophisticated later.
  61.     PIPE_RESET means we reset the terminal mode to what it was before
  62.     we started pine and then exec the command.
  63.  ----*/
  64. PIPE_S *
  65. open_system_pipe(command, outfile, errfile, mode)
  66.   char  *command;
  67.   char **outfile, **errfile;
  68.   int    mode;
  69. {
  70.     PIPE_S *syspipe = NULL;
  71.     FILE   *pipefp  = NULL;
  72.  
  73.     dprint(5, (debugfile, "Opening pipe: \"%s\" (%s%s%s%s%s%s)\n",command,
  74.            (mode & PIPE_WRITE)   ? "W":"", (mode & PIPE_READ)  ? "R":"",
  75.            (mode & PIPE_NOSHELL) ? "N":"", (mode & PIPE_PROT)  ? "P":"",
  76.            (mode & PIPE_USER)    ? "U":"", (mode & PIPE_RESET) ? "T":""));
  77.  
  78.     syspipe = (PIPE_S *)fs_get(sizeof(PIPE_S));
  79.     memset(syspipe, 0, sizeof(PIPE_S));
  80.  
  81.     /* fill in any output filenames */
  82.     if(!(mode & PIPE_READ)){
  83.     if(outfile && !*outfile)
  84.       *outfile = temp_nam(NULL, "pp");    /* asked for, but not named? */
  85.  
  86.     if(errfile && !*errfile)
  87.       *errfile = temp_nam(NULL, "pp");    /* ditto */
  88.     }
  89.  
  90.     interrupt_ok();
  91.     if((syspipe->mode = mode) & PIPE_RESET)
  92.         Raw(0);
  93.  
  94.     if(mode & PIPE_READ){
  95.         /* now, start the pipe */
  96.         pipefp = syspipe->in.f = popen(command, "r");
  97.         if (pipefp &&(mode & PIPE_DESC))
  98.             syspipe->in.d = fileno(pipefp);
  99.     }
  100.     else{
  101.         int wasstdout = -1;
  102.         int wasstderr = -1;
  103.         int output = -1;
  104.         /* if parent isn't reading, and we have a filename to write */
  105.         if(outfile){                    /* connect output to file */
  106.             output = creat(*outfile, S_IREAD|S_IWRITE);
  107.             if (output != -1)
  108.             {
  109.                 wasstdout = dup(STDOUT_FILENO);
  110.                 wasstderr = dup(STDERR_FILENO);
  111.                 dup2(output, STDOUT_FILENO);
  112.             if (mode & PIPE_STDERR)
  113.                     dup2(output, STDERR_FILENO);
  114.             else if(errfile)
  115.                     dup2(creat(*errfile, 0600), STDERR_FILENO);
  116.             }
  117.     }
  118.         if(mode & PIPE_WRITE){
  119.             /* Now, open the pipe */
  120.             pipefp = syspipe->out.f = popen(command, "w");
  121.             if (pipefp &&(mode & PIPE_DESC))
  122.                 syspipe->out.d = fileno(pipefp);
  123.         }else{
  124.             char   **ap, *p;
  125.             size_t   n;
  126.  
  127.             /* parse the arguments into argv */
  128.             for(p = command; *p && isspace((unsigned char)(*p)); p++)
  129.                 ;        /* swallow leading ws */
  130.             if(*p)
  131.                 syspipe->args = cpystr(p);
  132.             else{
  133.                 pipe_error_cleanup(&syspipe, "<null>", "execute",
  134.                                      "No command name found");
  135.                 return(NULL);
  136.             }
  137.     
  138.             for(p = syspipe->args, n = 2; *p; p++)    /* count the args */
  139.                 if(isspace((unsigned char)(*p))
  140.                    && *(p+1) && !isspace((unsigned char)(*(p+1))))
  141.                 n++;
  142.     
  143.             syspipe->argv = ap = (char **)fs_get((n+2) * sizeof(char *));
  144.             memset(syspipe->argv, 0, n * sizeof(char *));
  145.  
  146.             /*if (!(mode & PIPE_NOSHELL)){*/
  147.                 *ap++ = getenv("COMSPEC");
  148.                 *ap++ = "/C";
  149.             /*}*/
  150.  
  151.             for(p = syspipe->args; *p; ){        /* collect args */
  152.                 while(*p && isspace((unsigned char)(*p)))
  153.                     *p++ = '\0';
  154.  
  155.                 *ap++ = (*p) ? p : NULL;
  156.                 while(*p && !isspace((unsigned char)(*p)))
  157.                     p++;
  158.             }
  159.             *ap = NULL;
  160.  
  161.             /* make sure argv[0] exists in $PATH */
  162.             if(can_access_in_path(getenv("PATH"), syspipe->argv[0], EXECUTE_ACCESS) < 0){
  163.                 pipe_error_cleanup(&syspipe, syspipe->argv[0], "access",
  164.                     error_description(errno));
  165.                 return(NULL);
  166.             }
  167.             flush_status_messages(0);        /* just clean up display */
  168.             ClearScreen();
  169.             fflush(stdout);
  170.             /* And spawn the command */;
  171.             child_status = spawnvp(P_WAIT, syspipe->argv[0], syspipe->argv);
  172.             Raw(1);
  173.             dont_interrupt();
  174.             return(syspipe);
  175.         }
  176.         if (wasstdout!=-1){
  177.             dup2(STDOUT_FILENO, wasstdout);
  178.             close(wasstdout);
  179.         }
  180.         if (wasstderr!=-1){
  181.             dup2(STDERR_FILENO, wasstderr);
  182.             close(wasstderr);
  183.         }
  184.         if (output!=-1)
  185.             close(output);
  186.     }
  187.  
  188. /*  if(mode & PIPE_RESET) */
  189.         Raw(1);
  190.     dont_interrupt();
  191.  
  192.     if (pipefp == NULL) {
  193.         q_status_message1(SM_ORDER,3,3, "Error executing external command: %s",
  194.                                         error_description(errno));
  195.         fs_give((void **)&syspipe);
  196.         if(outfile)
  197.             fs_give((void **)outfile);
  198.         dprint(1, (debugfile, "CAN'T OPEN PIPE TO COMMAND: %s\n", command));
  199.     }
  200.  
  201.     return(syspipe);
  202. }
  203.  
  204.  
  205.  
  206. void
  207. pipe_error_cleanup(syspipe, cmd, op, res)
  208.     PIPE_S **syspipe;
  209.     char    *cmd, *op, *res;
  210. {
  211.     q_status_message3(SM_ORDER, 3, 3, "Pipe can't %s \"%.20s\": %s",
  212.               op, cmd, res);
  213.     dprint(1, (debugfile, "* * PIPE CAN'T %s(%s): %s\n", op, cmd, res));
  214.     fs_give((void **)syspipe);
  215. }
  216.  
  217.  
  218.  
  219. /*----------------------------------------------------------------------
  220.     Close pipe previously allocated and wait for child's death
  221.  
  222.   Args: syspipe -- address of pointer to struct returned by open_system_pipe
  223.   Returns: returns exit status of child or -1 if invalid syspipe
  224.  ----*/
  225. int
  226. close_system_pipe(syspipe)
  227.     PIPE_S **syspipe;
  228. {
  229.     int         status = child_status;
  230.  
  231.     if(!syspipe || !*syspipe)
  232.       return(-1);
  233.  
  234.     child_status = 0;
  235.  
  236.     if((*syspipe)->out.f)
  237.       status = pclose((*syspipe)->out.f);
  238.  
  239.     if((*syspipe)->in.f)
  240.       status = pclose((*syspipe)->in.f);
  241.  
  242.     ClearScreen();                /* No I/O to forked child */
  243.     ps_global->mangled_screen = 1;
  244.  
  245.     fs_give((void **)syspipe);
  246.     return(status);
  247. }
  248.